/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package server.thread;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.StringTokenizer;

/**
 *
 * @author SergioPeres
 */
public class HTTPFile {
    
    static final String HTML_START
            = "<html>"
            + "<title>HTTP POST Server in java</title>"
            + "<body>";

    static final String HTML_END
            = "</body>"
            + "</html>";
    
    Socket connectedClient = null;
    BufferedReader inFromClient = null;
    DataOutputStream outToClient = null;
    
    public HTTPFile(Socket client) {
        connectedClient = client;
    }
    
    public void postFile() {

        String currentLine = null, postBoundary = null,
                 contentLength = null;
        

        try {

            System.out.println("\nThe Client "
                    + connectedClient.getInetAddress() + ":" + connectedClient.getPort() + " is connected");

            inFromClient = new BufferedReader(new InputStreamReader(connectedClient.getInputStream()));
            outToClient = new DataOutputStream(connectedClient.getOutputStream());

            currentLine = inFromClient.readLine();
            System.out.println(currentLine);
            String headerLine = currentLine;
            StringTokenizer tokenizer = new StringTokenizer(headerLine);
            String httpMethod = tokenizer.nextToken();
            String httpQueryString = tokenizer.nextToken();

            System.out.println("1: " + currentLine + " ;");
            
            if (httpMethod.equals("GET")) {
                System.out.println("\n----- GET request");
                replyGET(httpQueryString);
            } else {
                //POST request
                System.out.println("\n----- POST request");
                do {
                    currentLine = inFromClient.readLine();
                    System.out.println("2: " + currentLine + " ;");
                    if (currentLine.indexOf("Content-Type: multipart/form-data") != -1) {
                        getFile(currentLine);
                    } //if							  				
                } while (inFromClient.ready()); //End of do-while
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void replyGET(String httpQueryString) throws Exception {
        if (httpQueryString.equals("/")) {
            // The default home page
            String responseString = "<html>"
                    + "<form action=\"http://127.0.0.1:8081\" enctype=\"multipart/form-data\""
                    + "method=\"post\">\n"
                    + "Enter the name of the File <input name=\"file\" type=\"file\"><br>\n"
                    + "<input value=\"Upload\" type=\"submit\">\n</form>\n"
                    + "Upload only text files."
                    + "</html>";
            sendResponse(200, responseString, false);
        } else {
            sendResponse(404, "<b>The Requested resource not found ...."
                    + "Usage: http://127.0.0.1:8081</b>", false);
        }
    }
    
    private void getFile(String currentLine) throws IOException, Exception {
        String filename = null, contentLength = null;
        
        PrintWriter fout = null;
        
        String boundary = currentLine.split("boundary=")[1];
                              // The POST boundary			  			 

        while (true) {
            currentLine = inFromClient.readLine();
            if (currentLine.indexOf("Content-Length:") != -1) {
                contentLength = currentLine.split(" ")[1];
                System.out.println("Content Length = " + contentLength);
                break;
            }
        }

        //Content length should be < 2MB
        if (Long.valueOf(contentLength) > 2000000L) {
            sendResponse(200, "File size should be < 2MB", false);
        }

        while (true) {
            currentLine = inFromClient.readLine();
            if (currentLine.indexOf("--" + boundary) != -1) {
                filename = inFromClient.readLine().split("filename=")[1].replaceAll("\"", "");
                String[] filelist = filename.split("\\" + System.getProperty("file.separator"));
                filename = filelist[filelist.length - 1];
                System.out.println("File to be uploaded = " + filename);
                break;
            }
        }

        String fileContentType = inFromClient.readLine().split(" ")[1];
        System.out.println("File content type = " + fileContentType);

        inFromClient.readLine(); //assert(inFromClient.readLine().equals("")) : "Expected line in POST request is "" ";

        fout = new PrintWriter(filename);
        String prevLine = inFromClient.readLine();
        currentLine = inFromClient.readLine();

        //Here we upload the actual file contents
        while (true) {
            if (currentLine.equals("--" + boundary + "--")) {
                fout.print(prevLine);
                break;
            } else {
                fout.println(prevLine);
            }
            prevLine = currentLine;
            currentLine = inFromClient.readLine();
        }

        sendResponse(200, "File " + filename + " Uploaded..", false);
        fout.close();
    }
    
    public void sendResponse(int statusCode, String responseString, boolean isFile) throws Exception {

        String statusLine = null;
        String serverdetails = "Server: Java HTTPServer";
        String contentLengthLine = null;
        String fileName = null;
        String contentTypeLine = "Content-Type: text/html" + "\r\n";
        FileInputStream fin = null;

        if (statusCode == 200) {
            statusLine = "HTTP/1.1 200 OK" + "\r\n";
        } else {
            statusLine = "HTTP/1.1 404 Not Found" + "\r\n";
        }

        if (isFile) {
            fileName = responseString;
            fin = new FileInputStream(fileName);
            contentLengthLine = "Content-Length: " + Integer.toString(fin.available()) + "\r\n";
            if (!fileName.endsWith(".htm") && !fileName.endsWith(".html")) {
                contentTypeLine = "Content-Type: \r\n";
            }
        } else {
            responseString = HTTPFile.HTML_START + responseString + HTTPFile.HTML_END;
            contentLengthLine = "Content-Length: " + responseString.length() + "\r\n";
        }

        outToClient.writeBytes(statusLine);
        outToClient.writeBytes(serverdetails);
        outToClient.writeBytes(contentTypeLine);
        outToClient.writeBytes(contentLengthLine);
        outToClient.writeBytes("Connection: close\r\n");
        outToClient.writeBytes("\r\n");

        if (isFile) {
            sendFile(fin, outToClient);
        } else {
            outToClient.writeBytes(responseString);
        }

        outToClient.close();
    }

    public void sendFile(FileInputStream fin, DataOutputStream out) throws Exception {
        byte[] buffer = new byte[1024];
        int bytesRead;

        while ((bytesRead = fin.read(buffer)) != -1) {
            out.write(buffer, 0, bytesRead);
        }
        fin.close();
    }
}
